#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "server.h"

#define N 64

#define CLIENT_LAMP_CTRL          "{\"lamp\":%s}"
#define CLIENT_FAN_CTRL           "{\"fan\":%s}"
#define CLIENT_SUNSHADE_CTRL      "{\"sunshade\":%s}"
#define CLIENT_ALARM_CTRL         "{\"alarm\":%s}"
#define CLIENT_IRR_CTRL           "{\"alarm\":%s}"
#define CLIENT_DOORLOOK_CTRL      "{\"alarm\":%s}"


static int sockfd = -1;
static int clientfd = -1;
int addrlen = sizeof(struct sockaddr_in);
static int client_ctrl;

int get_client_ctrl()
{
    return client_ctrl;
}

void *pthread_server (void *arg)
{
    int ret, nbytes;
    struct sockaddr_in clientaddr;
    char data[1024] = {0};
    // 5接收连接--accept
    printf("wait connecting...\n");
    printf("server = %d\n", sockfd);


    while (1)
    {

        clientfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen);
        if(clientfd < 0) {
            perror("accept err");
            return NULL;
        } else {
            printf("client %s connecting\n", inet_ntoa(clientaddr.sin_addr));
        }

        while(1){
            node_t tmp_data;
            memset(&tmp_data, 0, CONTROL_CMD_LEN);
            memset(data, 0, 1024);
            nbytes = recv(clientfd, &tmp_data, CONTROL_CMD_LEN, 0);
            if(nbytes > 0)
            {
                if(strlen(tmp_data.val.s_val))
                {
                    printf("invalid ctrl cmd from client\n");
                    continue;
                }
                switch(tmp_data.key)
                {
                case CLIENT_CMD_KEY_SWITCH:
                    client_ctrl = tmp_data.val.b_val;
                    break;
                case CLIENT_CMD_KEY_FAN:
                    sprintf(data, CLIENT_FAN_CTRL, tmp_data.val.s_val);
                    mqtt_publish(CTRL_PUB_TOPIC, data);
                    break;
                case CLIENT_CMD_KEY_IRR:
                    sprintf(data, CLIENT_IRR_CTRL, tmp_data.val.s_val);
                    mqtt_publish(CTRL_PUB_TOPIC, data);
                    break;
                case CLIENT_CMD_KEY_SUNSHADE:
                    sprintf(data, CLIENT_SUNSHADE_CTRL, tmp_data.val.s_val);
                    mqtt_publish(CTRL_PUB_TOPIC, data);
                    break;
                case CLIENT_CMD_KEY_ALARM:
                    sprintf(data, CLIENT_ALARM_CTRL, tmp_data.val.s_val);
                    mqtt_publish(CTRL_PUB_TOPIC, data);
                    break;
                case CLIENT_CMD_KEY_LAMP:
                    sprintf(data, CLIENT_LAMP_CTRL, tmp_data.val.s_val);
                    mqtt_publish(CTRL_PUB_TOPIC, data);
                    break;
                case CLIENT_CMD_KEY_DOORLOOK:
                    sprintf(data, CLIENT_DOORLOOK_CTRL, tmp_data.val.s_val);
                    mqtt_publish(CTRL_PUB_TOPIC, data);
                    break;
                default:
                    printf("invalid key\n");
                    break;
                }

            }
            else if(nbytes == 0)
            {
                printf("client quit\n");
                clientfd = -1;
                close(clientfd);
                break;
            }
            else if (nbytes < 0)
            {
                perror("nb < 0");
                clientfd = -1;
                close(clientfd);
                break;
                //continue;
            }
        }
    }

}

int init_network(int port)
{
    printf("prot = %d\n", port);
    struct sockaddr_in addr;
    pthread_t pid;

    // 1创建一个套接字--socket
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0) {
        perror("socket err");
        return -1;
    }

    // 2定义套接字地址--sockaddr_in
    bzero(&addr, addrlen);
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);

    int reuse = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
    // 3绑定套接字--bind
    if(bind(sockfd, (struct sockaddr *)&addr, addrlen) < 0) {
        perror("bind err");
        return -1;
    }

    // 4启动监听--listen
    if(listen(sockfd, 5) < 0) {
        perror("listen err");
        return -1;
    }

    return pthread_create(&pid, NULL, pthread_server, NULL);
}

/**
 * @brief 发送给客户端
 * @return 发送成功字节数 -1发送失败或者无客户端
 */
int send_data(node_t data)
{
    if(clientfd > 0){  //代表有连接了
        return send(clientfd, &data, sizeof(node_t), 0);
    }else{
        printf("no client connect\n");
        return -1;
    }
}

void close_network()
{
    close(clientfd);
    close(sockfd);
}
